import { userStore } from "@/store/index";

// 定义页面导航的选项接口
interface NavigateOptions {
  query?: Record<string, any>; // 页面参数
  events?: Record<string, Function>; // 页面间事件通信
  success?: (res: WechatMiniprogram.NavigateToSuccessCallbackResult) => void;
  fail?: (res: WechatMiniprogram.GeneralCallbackResult) => void;
  complete?: (res: WechatMiniprogram.GeneralCallbackResult) => void;
}

/**
 * 存放常用或关键页面的路径常量集合。
 */
export const PagePaths = {
  index: "/pages/index/index",
  login: "/pages/login/index",
  forbidden: "/pages/forbidden/index",
};

// --- 新增类型定义，增强代码可读性和健壮性 ---

// 定义角色类型，可以是字符串字面量的联合类型，以获得更好的类型提示
type Role = "master" | "recycle" | "admin" | "editor" | string;

// 定义权限策略
type RolePolicy = "ANY" | "ALL";

// 定义单个页面的权限规则
interface RoleRule {
  roles: Role[]; // 需要的角色列表
  policy?: RolePolicy; // 权限策略，默认为 'ANY'
}

// ----------------------------------------------

class Router {
  /**
   * 需要【登录认证】的页面路径匹配规则（正则表达式数组）。
   * 这是第一道防线：用户是否登录。
   */
  private authRequiredPatterns: RegExp[] = [
    /^\/pages\/manage\/pages\//,
    /^\/pages\/recycle\//,
    /^\/pages\/second\//,
    /^\/pages\/im\//,
    /^\/pages\/me\//,
  ];

  /**
   * 【角色授权】配置：定义页面的角色访问权限。
   * 这是第二道防线：用户是否有权访问。
   * - key: 匹配页面路径的正则表达式字符串。
   * - value: 权限规则对象 (RoleRule)。
   *
   * @example
   * // /pages/manage/pages/dashboard/ 页面需要 'master' 或 'admin' 角色
   * "^\/pages\/manage\/pages\/dashboard\/": { roles: ['master', 'admin'] },
   *
   * // /pages/manage/pages/content/ 页面需要同时拥有 'master' 和 'editor' 角色
   * "^\/pages\/manage\/pages\/content\/": { roles: ['master', 'editor'], policy: 'ALL' },
   */
  private pagePermissions: Record<string, RoleRule> = {
    // 示例：manage下的所有页面都需要 'master' 角色
    "^/pages/manage/pages/": { roles: ["master"] },
    // 示例：更具体的页面可以覆盖上面的规则，例如只有admin能访问某个特定页面
    "^/pages/manage/pages/system_settings/": { roles: ["admin"] },
    // 示例：回收页面，'recycle'或'master'角色可以访问
    // 注意：由于角色继承的存在，这里只需定义基础角色即可
    "^/pages/recycle/address_list/": { roles: ["recycle"] },
  };

  /**
   * 角色继承关系定义。
   * key是父角色，value是其继承的子角色数组。
   * 系统会自动展开用户的角色，例如拥有 'master' 角色的用户，将被视为同时拥有 'recycle' 和 'editor' 角色。
   */
  private roleHierarchy: Record<Role, Role[]> = {
    master: ["recycle", "editor"], // master 继承了 recycle 和 editor 的权限
    admin: ["master"], // admin 继承了 master 的所有权限（包括间接继承的）
  };

  private loginPage: string = PagePaths.login;
  private forbiddenPage: string = PagePaths.forbidden;

  /**
   * 内部私有方法：构建带参数的URL
   */
  private buildUrl(path: string, query?: Record<string, any>): string {
    if (!query || Object.keys(query).length === 0) {
      return path;
    }
    const queryString = Object.keys(query)
      .map((key) => `${key}=${encodeURIComponent(query[key])}`)
      .join("&");
    return `${path}?${queryString}`;
  }

  /**
   * 内部私有方法：根据角色继承关系，计算用户所拥有的所有有效角色。
   * @returns {Set<Role>} 一个包含用户所有直接和间接角色的集合。
   */
  private getUserEffectiveRoles(): Set<Role> {
    const userRoles = userStore.roles || [];
    const effectiveRoles = new Set<Role>(userRoles);
    const rolesToProcess = [...userRoles];

    while (rolesToProcess.length > 0) {
      const currentRole = rolesToProcess.shift()!;
      const inheritedRoles = this.roleHierarchy[currentRole];
      if (inheritedRoles) {
        for (const inheritedRole of inheritedRoles) {
          if (!effectiveRoles.has(inheritedRole)) {
            effectiveRoles.add(inheritedRole);
            rolesToProcess.push(inheritedRole);
          }
        }
      }
    }
    return effectiveRoles;
  }

  /**
   * 内部私有方法：检查用户对特定页面是否有访问权限（授权）。
   * @param path 目标页面的路径 (不含query)
   * @returns {boolean} 是否有权访问
   */
  private checkAuthorization(path: string): boolean {
    let requiredRule: RoleRule | null = null;

    // 遍历权限配置，查找最匹配的规则
    // 注意：此简单实现会采用第一个匹配的规则，可以通过调整配置顺序来控制优先级
    for (const patternStr in this.pagePermissions) {
      const pattern = new RegExp(patternStr);
      if (pattern.test(path)) {
        requiredRule = this.pagePermissions[patternStr];
        break;
      }
    }

    // 如果没有找到规则，说明此页面不需要特定角色权限，直接放行
    if (!requiredRule) {
      return true;
    }

    const userEffectiveRoles = this.getUserEffectiveRoles();
    const { roles: requiredRoles, policy = "ANY" } = requiredRule;

    if (policy === "ALL") {
      // 需要满足所有角色
      return requiredRoles.every((role) => userEffectiveRoles.has(role));
    } else {
      // 只需要满足任意一个角色 (默认)
      return requiredRoles.some((role) => userEffectiveRoles.has(role));
    }
  }

  /**
   * 内部私有方法：整合【登录认证】和【角色授权】检查。
   * @param path 目标页面的路径 (不含query)
   * @param options 导航的原始参数
   * @returns {boolean} 是否允许跳转
   */
  private checkAuth(path: string, options?: NavigateOptions): boolean {
    if (path === this.loginPage || path === this.forbiddenPage) {
      return true; // 目标是登录页或禁止访问页，直接放行
    }

    // --- 步骤一：登录认证 (Authentication) ---
    const needsLogin = this.authRequiredPatterns.some((pattern) =>
      pattern.test(path)
    );
    if (needsLogin && !userStore.islogin) {
      console.warn(`页面 [${path}] 需要登录，将跳转至登录页。`);
      const redirectUrl = this.buildUrl(path, options?.query);
      wx.navigateTo({
        url: this.buildUrl(this.loginPage, {
          redirect: encodeURIComponent(redirectUrl),
        }),
      });
      return false; // 认证失败，阻止导航
    }

    // --- 步骤二：角色授权 (Authorization) ---
    // 只有在需要登录的页面（或所有页面，取决于业务）才进行角色检查
    if (needsLogin) {
      const isAuthorized = this.checkAuthorization(path);
      if (!isAuthorized) {
        console.error(`用户权限不足，无法访问页面 [${path}]。`);
        wx.showToast({
          title: "对不起，您的权限不足",
          icon: "none",
          duration: 2000,
        });
        // 可选：跳转到统一的无权限页面
        // this.redirectTo(this.forbiddenPage);
        return false; // 授权失败，阻止导航
      }
    }

    return true; // 认证和授权均通过
  }

  // --- 公共导航方法 (保持不变) ---

  public navigateTo(path: string, options?: NavigateOptions) {
    if (!this.checkAuth(path, options)) return;
    wx.navigateTo({
      url: this.buildUrl(path, options?.query),
      events: options?.events,
      success: options?.success,
      fail: options?.fail,
      complete: options?.complete,
    });
  }

  public redirectTo(path: string, options?: NavigateOptions) {
    if (!this.checkAuth(path, options)) return;
    wx.redirectTo({
      url: this.buildUrl(path, options?.query),
      success: options?.success,
      fail: options?.fail,
      complete: options?.complete,
    });
  }

  public reLaunch(path: string, options?: NavigateOptions) {
    if (!this.checkAuth(path, options)) return;
    wx.reLaunch({
      url: this.buildUrl(path, options?.query),
      success: options?.success,
      fail: options?.fail,
      complete: options?.complete,
    });
  }

  public navigateBack(delta: number = 1) {
    wx.navigateBack({ delta });
  }

  public toHome(options?: NavigateOptions) {
    this.reLaunch(PagePaths.index, options);
  }

  // 新增一个方便跳转到无权限页面的方法
  public toForbidden(options?: NavigateOptions) {
    this.redirectTo(this.forbiddenPage, options);
  }
}

// 导出单例
export const router = new Router();
